import struct
import cv2
import numpy as np


class Pic2Pix:
    __dir = {10: "a", 11: "b", 12: "c", 13: "d", 14: "e", 15: "f"}

    def __init__(self, pixel_shape, path):
        self.p_shape = pixel_shape
        self.path = path
        self.__code = []
        self.__coded = []
        self.__img_l = []
        self.img = self.__read_pic(self.path)
        self.img_size = self.img.shape
        self.pixel_space = None


    def __norm_img(self, img, ifshow=False, ifwrite=False):
        if self.img_size[0] != self.img_size[1]:
            if self.img_size[0] > self.img_size[1]:
                d = self.img_size[0] - self.img_size[1]
                img = img[(d // 2):(self.img_size[0] - d // 2), 0:self.img_size[1]]
            else:
                d = self.img_size[1] - self.img_size[0]
                img = img[0:self.img_size[0], (d // 2):(self.img_size[1] - d // 2)]
        if ifshow:
            cv2.namedWindow("cutted", cv2.WINDOW_NORMAL)
            cv2.imshow("cutted", img)
        if ifwrite:
            cv2.imwrite("cutted.jpg",img)

        sub_size = img.shape[0] // self.p_shape[0]
        for i in range(self.p_shape[0]):
            for j in range(self.p_shape[1]):
                self.__img_l.append(img[j * sub_size:(j + 1) * sub_size, i * sub_size:(i + 1) * sub_size])
        return 0

    def __read_pic(self, ifshow=False, ifwrite=False):
        img = cv2.imread(self.path)
        if ifshow:
            cv2.namedWindow("yuantu", cv2.WINDOW_NORMAL)
            cv2.imshow("yuantu", img)
        if ifwrite:
            cv2.imwrite("yuantu.jpg", img)
        return img

    def __dec2hex(self):
        self.__coded = []
        for i in self.__code:
            if i > 9:
                self.__coded.append(self.__dir[i])
            else:
                self.__coded.append(str(i))

        return 0

    def bin_Pic(self, kernel=(3,3), range=(170,255), ifshow=False, ifwrite=False):
        g_img = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
        bl_img = cv2.blur(g_img, kernel)
        _, th_img = cv2.threshold(bl_img, thresh=range[0], maxval=range[1], type=cv2.THRESH_BINARY)
        if ifshow:
            cv2.namedWindow("thresh", cv2.WINDOW_NORMAL)
            cv2.imshow("thresh", th_img)
        if ifwrite:
            cv2.imwrite("thresh.jpg", self.img)
        self.__norm_img(th_img,ifshow)
        return 0

    def pixel(self):
        sub_sum = self.__img_l[0].shape[0] ** 2
        self.pixel_space = np.zeros(shape=self.p_shape, dtype=int)
        for a in range(len(self.__img_l)):
            sub_img = self.__img_l[a] / 255
            if sub_img.sum() / sub_sum > 0.5:
                self.pixel_space[a // 8][a % 8] = 1
            else:
                self.pixel_space[a // 8][a % 8] = 0
        return 0


    def pix_code_1(self):
        file = open("__code.txt", "w")
        for i in self.pixel_space:
            self.__code = [0, 0]
            for j in range(4):
                self.__code[0] *= 2
                self.__code[0] += i[j]
            for j in range(4):
                self.__code[1] *= 2
                self.__code[1] += i[j + 4]
            self.__dec2hex()
            file.write("0x")
            for s in range(2):
                file.write(self.__coded[s])
            file.write(",")
        return 0

    def pix_code(self):
        s = 0
        file = open("__code.bin", "wb")
        for i in self.pixel_space:
            s = 0
            for j in range(self.p_shape[0]):
                s *= 2
                s += i[j]
            a = struct.pack('B', s)
            file.write(a)
        return 0